package api

import (
	"context"
	"net/http"

	"gitee.com/yanwc/gozero-utils/errx"
	"github.com/pkg/errors"
	"github.com/zeromicro/go-zero/core/logx"

	// "github.com/zeromicro/go-zero/internal/trace"
	"github.com/zeromicro/go-zero/rest/httpx"
	"go.opentelemetry.io/otel/trace"
	"google.golang.org/grpc/status"
)

func HttpResult(r *http.Request, w http.ResponseWriter, resp interface{}, err error) {
	ctx := r.Context()
	var traceID, spanID string
	if err == nil {
		// 成功返回
		r := Success(resp)
		httpx.WriteJson(w, http.StatusOK, r)
	} else {
		// 错误返回
		errcode := errx.SERVER
		errmsg := err.Error()
		statusCode := http.StatusInternalServerError
		causeErr := errors.Cause(err) // err类型
		// 自定义code返回http200错误,否则返回服务器错误500
		if e, ok := causeErr.(*errx.Error); ok { // 自定义错误类型
			errcode = e.GetErrCode()
			errmsg = e.Error()
			if e.GetErrCode() != errx.BIZ {
				logx.WithContext(r.Context()).Errorf("API : %+v ", err)
			}

			if e.GetErrCode() == errx.TOKEN_EXPIRE {
				statusCode = http.StatusUnauthorized
			} else {
				statusCode = http.StatusOK
			}
			traceID = TraceIDFromContext(ctx)
			spanID = SpanIDFromContext(ctx)

		} else {
			if gstatus, ok := status.FromError(causeErr); ok { // grpc err错误
				grpcCode := uint32(gstatus.Code())
				if errx.IsCodeErr(errx.Code(grpcCode)) { // 自定义错误
					errcode = errx.Code(grpcCode)
					errmsg = gstatus.Message()
					if errx.Code(grpcCode) == errx.TOKEN_EXPIRE {
						statusCode = http.StatusUnauthorized
					} else {
						statusCode = http.StatusOK
					}
				} else {
					errcode = errx.Code(errx.SERVER)
					errmsg = "rpc 调用失败"
				}
			}

			traceID = TraceIDFromContext(ctx)
			spanID = SpanIDFromContext(ctx)
			logx.WithContext(r.Context()).Errorf("API : %+v ", err)
		}

		httpx.WriteJson(w, statusCode, FailWithTrace(errcode, errmsg, spanID, traceID))
	}
}

func SpanIDFromContext(ctx context.Context) string {
	spanCtx := trace.SpanContextFromContext(ctx)
	if spanCtx.HasSpanID() {
		return spanCtx.SpanID().String()
	}

	return ""
}

func TraceIDFromContext(ctx context.Context) string {
	spanCtx := trace.SpanContextFromContext(ctx)
	if spanCtx.HasTraceID() {
		return spanCtx.TraceID().String()
	}

	return ""
}
